/*
 * RegExFilenameFilter.java
 *
 * Created on February 20, 2006, 10:01 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package custom.io;

import java.io.File;
import java.io.FilenameFilter;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

/**
 *
 * @author David Armstrong
 */
public class RegExFilenameFilter implements FilenameFilter {

    private Pattern pattern = null;
    private String regex = null;
    private int filenameFlags = FILTERFILENAMES;
    public final static int FILTERFILENAMES = 1;
    public final static int FILTERDIRNAMES = 2;
    public final static int EXCLUSIVE = 4;

    /** Creates a new instance of RegExFilenameFilter */
    public RegExFilenameFilter() {
        pattern = Pattern.compile("");
    }

    public RegExFilenameFilter(int regexFlags) {
        pattern = Pattern.compile("", regexFlags);
    }

    public RegExFilenameFilter(int regexFlags, int filenameFlags) {
        pattern = Pattern.compile("", regexFlags);
        setFilenameFlags(filenameFlags);
    }

    public RegExFilenameFilter(String regex) {
        this.regex = regex;
        pattern = Pattern.compile(regex);
    }

    public RegExFilenameFilter(String regex, int regexFlags) {
        this.regex = regex;
        pattern = Pattern.compile(regex, regexFlags);
    }

    public RegExFilenameFilter(String regex, int regexFlags, int filenameFlags) {
        this.regex = regex;
        pattern = Pattern.compile(regex, regexFlags);
        setFilenameFlags(filenameFlags);
    }

    public void setFilenameFlags(int filenameFlags) {
        this.filenameFlags = filenameFlags;
    }

    public int getFilenameFlags() {
        return filenameFlags;
    }

    public void turnOnFilenameFlag(int filenameFlag) {
        if (filenameFlag == FILTERFILENAMES || filenameFlag == FILTERDIRNAMES || filenameFlag == EXCLUSIVE) {
            // Make sure flag is not already set.
            if ((filenameFlags & filenameFlag) == 0) {
                filenameFlags |= filenameFlag;
            }
        }
    }

    public void turnOffFilenameFlag(int filenameFlag) {
        if (filenameFlag == FILTERFILENAMES || filenameFlag == FILTERDIRNAMES || filenameFlag == EXCLUSIVE) {
            // Make sure flag is already set.
            if ((filenameFlags & filenameFlag) > 0) {
                filenameFlags &= ~filenameFlag;
            }
        }
    }

    public boolean isFilenameFlagSet(int filenameFlag) {
        boolean set = false;
        if (filenameFlag == FILTERFILENAMES || filenameFlag == FILTERDIRNAMES || filenameFlag == EXCLUSIVE) {
            set = (filenameFlags & filenameFlag) > 0;
        }
        return set;
    }

    public void compile(String regex) {
        this.regex = regex;
        pattern = Pattern.compile(regex);
    }

    public void compile(String regex, int flags) {
        this.regex = regex;
        pattern = Pattern.compile(regex, flags);
    }

    public void setRegexFlags(int regexFlags) {
        pattern = Pattern.compile(regex != null ? regex : "", regexFlags);
    }

    public boolean accept(File directory, String name) {
        boolean status = true;
        Matcher matcher = null;

        if (pattern != null && directory != null && name != null) {
            File fileName = new File(directory.toString() + System.getProperty("file.separator") + name);

            /* If file is a regular file, make sure we are supposed to filter files before doing so.
             * If file is a directory, make sure we are supposed to filter directories before doing so. */
            if ((fileName.isFile() && (filenameFlags & FILTERFILENAMES) > 0) ||
                    (fileName.isDirectory() && (filenameFlags & FILTERDIRNAMES) > 0)) {
                matcher = pattern.matcher(name);
                // If exclusive is true, set status to true if the matcher returns false.
                status = ((filenameFlags & EXCLUSIVE) > 0) ? !matcher.find() : matcher.find();
            }
        }

        return status;
    }

    public int getRegexFlags() {
        return (pattern != null ? pattern.flags() : 0);
    }

    public void turnOnRegexFlag(int regexFlag) {
        if (regexFlag == Pattern.LITERAL || regexFlag == Pattern.CASE_INSENSITIVE) {
            // Make sure flag is not already set.
            int regexFlags = getRegexFlags();
            if ((regexFlags & regexFlag) == 0) {
                regexFlags |= regexFlag;
            }
            setRegexFlags(regexFlags);
        }
    }

    public void turnOffRegexFlag(int regexFlag) {
        if (regexFlag == Pattern.LITERAL || regexFlag == Pattern.CASE_INSENSITIVE) {
            // Make sure flag is already set.
            int regexFlags = getRegexFlags();
            if ((regexFlags & regexFlag) > 0) {
                regexFlags &= ~regexFlag;
            }
            setRegexFlags(regexFlags);
        }
    }

    public boolean isRegexFlagSet(int regexFlag) {
        boolean set = false;
        if (regexFlag == Pattern.LITERAL || regexFlag == Pattern.CASE_INSENSITIVE) {
            int regexFlags = getRegexFlags();
            set = (regexFlags & regexFlag) > 0;
        }
        return set;
    }

    public String pattern() {
        return (pattern != null ? pattern.pattern() : null);
    }
}
